2019. 02. 27. 산업수학 아카데미

  • 국가수리과학연구소 연구원 정재원

-1. 안내

안녕하세요?

자료를 원하시는 분들이 많아 수업 자료를(html 파일) 공유해 드립니다. 맨 마지막 치킨ㅋㅋ 엑셀파일은 실제 주소여서 따로 제공하지 않겠습니다. 다른 주소로 연습하시거나 개별적으로 만들어서 사용하시기 바랍니다. Google Maps API 용 Key는 간단한 정보(카드)만 입력하면 받으실 수 있습니다. 소소하게 교육용으로 조금 사용하는 것은 결재하지 않는 것으로 알고 있습니다. (추후 바뀌는 것은 스스로 체크하시기 바랍니다.) 아래 코드에는 개별적으로 제공받은 키를 넣으시면 됩니다.

짧은 시간 급히 준비한 내용이라 일부 효율적인 코딩이 아닐 수 있으니 참고해 주세요. 제 파일을 비롯하여 아카데미에서 배포된 모든 자료들은 참석한 분들에게만 공유된 자료입니다. 개인적인 교육용으로만 참고하시고 다른 분들께 전달하거나 절대로 다른 목적으로 사용하지 마시길 부탁드립니다. 부족한 준비에도 열심히 따라와 주셔서 감사합니다.^^ 많은 도움이 되었기를~~~

0. 목차

    1. 서울시 주택 데이터 살펴보기
    1. folium을 활용하여 지도에 표현하기
      • json 파일 들여다보기
      • 구별 평균 연면적, 거래금액, 건축년도 등의 정보를 지도에 나타내기
      • 주어진 조건에 맞는 집 찾기
    1. 연습문제 : 부산광역시
    1. 참고
In [1]:
import pandas as pd
import matplotlib.pyplot as plt 
import seaborn as sns
%matplotlib inline

plt.rc('font', family='Malgun Gothic')

1. 서울시 주택 데이터 살펴보기

In [2]:
df = pd.read_excel("data/2018_modified_data.xlsx")
  • 가정 : 주어진 데이터는 건물 하나 전체의 정보이지만, 단일 세대로 간주하고 진행
In [3]:
df.head()
Out[3]:
시군구 주택유형 도로조건 연면적(㎡) 대지면적(㎡) 거래금액(만원) 건축년도 연도 SiDo SiGunGu DongLi ID
0 강원도 강릉시 강동면 모전리 단독 8 64.20 205.0 10520 2018 2018 1 강원도 강릉시 모전리(강동면) 강릉
1 강원도 강릉시 견소동 단독 12 35.60 81.0 4000 1990 2018 1 강원도 강릉시 견소동 강릉
2 강원도 강릉시 교동 단독 12 99.90 160.0 16500 1982 2018 1 강원도 강릉시 교동 강릉
3 강원도 강릉시 교동 단독 12 326.88 211.6 64300 2005 2018 1 강원도 강릉시 교동 강릉
4 강원도 강릉시 교동 단독 8 154.99 240.2 19000 1980 2018 1 강원도 강릉시 교동 강릉
In [4]:
del df['도로조건']
del df['연도']
del df['월']
del df['DongLi']
In [5]:
df.head()
Out[5]:
시군구 주택유형 연면적(㎡) 대지면적(㎡) 거래금액(만원) 건축년도 SiDo SiGunGu ID
0 강원도 강릉시 강동면 모전리 단독 64.20 205.0 10520 2018 강원도 강릉시 강릉
1 강원도 강릉시 견소동 단독 35.60 81.0 4000 1990 강원도 강릉시 강릉
2 강원도 강릉시 교동 단독 99.90 160.0 16500 1982 강원도 강릉시 강릉
3 강원도 강릉시 교동 단독 326.88 211.6 64300 2005 강원도 강릉시 강릉
4 강원도 강릉시 교동 단독 154.99 240.2 19000 1980 강원도 강릉시 강릉
In [6]:
df['SiDo'].unique()
Out[6]:
array(['강원도', '경기도', '경상남도', '경상북도', '광주광역시', '대구광역시', '대전광역시', '부산광역시',
       '서울특별시', '세종특별자치시', '울산광역시', '인천광역시', '전라남도', '전라북도', '제주특별자치도',
       '충청남도', '충청북도'], dtype=object)
In [7]:
df['SiGunGu'].unique()
Out[7]:
array(['강릉시', '고성군', '동해시', '삼척시', '속초시', '양구군', '양양군', '영월군', '원주시',
       '인제군', '정선군', '철원군', '춘천시', '태백시', '평창군', '홍천군', '화천군', '횡성군',
       '가평군', '고양덕양구', '고양일산동구', '고양일산서구', '과천시', '광명시', '광주시', '구리시',
       '군포시', '김포시', '남양주시', '동두천시', '부천시', '성남분당구', '성남수정구', '성남중원구',
       '수원권선구', '수원영통구', '수원장안구', '수원팔달구', '시흥시', '안산단원구', '안산상록구', '안성시',
       '안양동안구', '안양만안구', '양주시', '양평군', '여주시', '연천군', '오산시', '용인기흥구',
       '용인수지구', '용인처인구', '의왕시', '의정부시', '이천시', '파주시', '평택시', '포천시', '하남시',
       '화성시', '거제시', '거창군', '김해시', '남해군', '밀양시', '사천시', '산청군', '양산시',
       '의령군', '진주시', '창녕군', '창원마산합포구', '창원마산회원구', '창원성산구', '창원의창구',
       '창원진해구', '통영시', '하동군', '함안군', '함양군', '합천군', '경산시', '경주시', '고령군',
       '구미시', '군위군', '김천시', '문경시', '봉화군', '상주시', '성주군', '안동시', '영덕군',
       '영양군', '영주시', '영천시', '예천군', '울릉군', '울진군', '의성군', '청도군', '청송군',
       '칠곡군', '포항남구', '포항북구', '광산구', '남구', '동구', '북구', '서구', '달서구', '달성군',
       '수성구', '중구', '대덕구', '유성구', '강서구', '금정구', '기장군', '동래구', '부산진구',
       '사상구', '사하구', '수영구', '연제구', '영도구', '해운대구', '강남구', '강동구', '강북구',
       '관악구', '광진구', '구로구', '금천구', '노원구', '도봉구', '동대문구', '동작구', '마포구',
       '서대문구', '서초구', '성동구', '성북구', '송파구', '양천구', '영등포구', '용산구', '은평구',
       '종로구', '중랑구', '금남면', '연서면', '장군면', '전동면', '전의면', '조치원읍', '울주군',
       '강화군', '계양구', '남동구', '미추홀구', '부평구', '연수구', '옹진군', '강진군', '고흥군',
       '곡성군', '광양시', '구례군', '나주시', '담양군', '목포시', '무안군', '보성군', '순천시',
       '신안군', '여수시', '영광군', '영암군', '완도군', '장성군', '장흥군', '진도군', '함평군',
       '해남군', '화순군', '고창군', '군산시', '김제시', '남원시', '무주군', '부안군', '순창군',
       '완주군', '익산시', '임실군', '장수군', '전주덕진구', '전주완산구', '정읍시', '진안군', '서귀포시',
       '제주시', '계룡시', '공주시', '금산군', '논산시', '당진시', '보령시', '부여군', '서산시',
       '서천군', '아산시', '예산군', '천안동남구', '천안서북구', '청양군', '태안군', '홍성군', '괴산군',
       '단양군', '보은군', '영동군', '옥천군', '음성군', '제천시', '증평군', '진천군', '청주상당구',
       '청주서원구', '청주청원구', '청주흥덕구', '충주시', '부강면', '연동면', '소정면', '연기면',
       '고운동'], dtype=object)
In [8]:
df['ID'].unique()
Out[8]:
array(['강릉', '고성', '동해', '삼척', '속초', '양구', '양양', '영월', '원주', '인제', '정선',
       '철원', '춘천', '태백', '평창', '홍천', '화천', '횡성', '가평', '고양 덕양', '고양 일산동',
       '고양 일산서', '과천', '광명', '광주', '구리', '군포', '김포', '남양주', '동두천', '부천',
       '성남 분당', '성남 수정', '성남 중원', '수원 권선', '수원 영통', '수원 장안', '수원 팔달',
       '시흥', '안산 단원', '안산 상록', '안성', '안양 동안', '안양 만안', '양주', '양평', '여주',
       '연천', '오산', '용인 기흥', '용인 수지', '용인 처인', '의왕', '의정부', '이천', '파주',
       '평택', '포천', '하남', '화성', '거제', '거창', '김해', '남해', '밀양', '사천', '산청',
       '양산', '의령', '진주', '창녕', '창원 마산합포', '창원 마산회원', '창원 성산', '창원 의창',
       '창원 진해', '통영', '하동', '함안', '함양', '합천', '경산', '경주', '고령', '구미',
       '군위', '김천', '문경', '봉화', '상주', '성주', '안동', '영덕', '영양', '영주', '영천',
       '예천', '울릉', '울진', '의성', '청도', '청송', '칠곡', '포항 남', '포항 북', '광주 광산',
       '광주 남구', '광주 동구', '광주 북구', '광주 서구', '대구 남구', '대구 달서', '대구 달성',
       '대구 동구', '대구 북구', '대구 서구', '대구 수성', '대구 중구', '대전 대덕', '대전 동구',
       '대전 서구', '대전 유성', '대전 중구', '부산 강서', '부산 금정', '부산 기장', '부산 남구',
       '부산 동구', '부산 동래', '부산 부산진', '부산 북구', '부산 사상', '부산 사하', '부산 서구',
       '부산 수영', '부산 연제', '부산 영도', '부산 중구', '부산 해운대', '서울 강남', '서울 강동',
       '서울 강북', '서울 강서', '서울 관악', '서울 광진', '서울 구로', '서울 금천', '서울 노원',
       '서울 도봉', '서울 동대문', '서울 동작', '서울 마포', '서울 서대문', '서울 서초', '서울 성동',
       '서울 성북', '서울 송파', '서울 양천', '서울 영등포', '서울 용산', '서울 은평', '서울 종로',
       '서울 중구', '서울 중랑', '세종', '울산 남구', '울산 동구', '울산 북구', '울산 울주',
       '울산 중구', '인천 강화', '인천 계양', '인천 남동', '인천 동구', '인천 미추홀', '인천 부평',
       '인천 서구', '인천 연수', '인천 옹진', '인천 중구', '강진', '고흥', '곡성', '광양', '구례',
       '나주', '담양', '목포', '무안', '보성', '순천', '신안', '여수', '영광', '영암', '완도',
       '장성', '장흥', '진도', '함평', '해남', '화순', '고창', '군산', '김제', '남원', '무주',
       '부안', '순창', '완주', '익산', '임실', '장수', '전주 덕진', '전주 완산', '정읍', '진안',
       '서귀포', '제주', '계룡', '공주', '금산', '논산', '당진', '보령', '부여', '서산', '서천',
       '아산', '예산', '천안 동남', '천안 서북', '청양', '태안', '홍성', '괴산', '단양', '보은',
       '영동', '옥천', '음성', '제천', '증평', '진천', '청주 상당', '청주 서원', '청주 청원',
       '청주 흥덕', '충주'], dtype=object)
In [9]:
Seoul = df[df['SiDo']=='서울특별시']
Seoul.head()
Out[9]:
시군구 주택유형 연면적(㎡) 대지면적(㎡) 거래금액(만원) 건축년도 SiDo SiGunGu ID
4520 서울특별시 강남구 개포동 단독 210.48 117.1 111000 1990 서울특별시 강남구 서울 강남
4521 서울특별시 강남구 논현동 다가구 249.12 240.8 360000 1985 서울특별시 강남구 서울 강남
4522 서울특별시 강남구 논현동 다가구 803.84 282.3 490000 2000 서울특별시 강남구 서울 강남
4523 서울특별시 강남구 논현동 단독 313.39 177.1 207000 2000 서울특별시 강남구 서울 강남
4524 서울특별시 강남구 논현동 단독 840.22 375.8 470000 1985 서울특별시 강남구 서울 강남
In [10]:
Seoul.reset_index(inplace=True, drop=True)
Seoul.head()
Out[10]:
시군구 주택유형 연면적(㎡) 대지면적(㎡) 거래금액(만원) 건축년도 SiDo SiGunGu ID
0 서울특별시 강남구 개포동 단독 210.48 117.1 111000 1990 서울특별시 강남구 서울 강남
1 서울특별시 강남구 논현동 다가구 249.12 240.8 360000 1985 서울특별시 강남구 서울 강남
2 서울특별시 강남구 논현동 다가구 803.84 282.3 490000 2000 서울특별시 강남구 서울 강남
3 서울특별시 강남구 논현동 단독 313.39 177.1 207000 2000 서울특별시 강남구 서울 강남
4 서울특별시 강남구 논현동 단독 840.22 375.8 470000 1985 서울특별시 강남구 서울 강남
In [11]:
AveSeoul = pd.pivot_table(Seoul, index=['SiGunGu'])
AveSeoul
Out[11]:
거래금액(만원) 건축년도 대지면적(㎡) 연면적(㎡)
SiGunGu
강남구 398544.196809 1991.968085 269.402340 423.079840
강동구 115203.342155 1988.083176 162.797845 253.092287
강북구 56433.446694 1984.213225 118.861916 151.125250
강서구 90370.710784 1986.127451 161.606373 222.836422
관악구 103683.726107 1988.480186 140.718112 217.059289
광진구 126033.411255 1987.821068 147.314401 243.697662
구로구 68997.029340 1985.608802 146.530416 180.150978
금천구 85135.947917 1982.658854 156.545391 226.951797
노원구 51963.837638 1965.431734 106.748782 139.094834
도봉구 67213.194268 1986.888535 146.358917 211.721465
동대문구 67130.329749 1980.124552 113.798916 137.901434
동작구 111311.605263 1986.986068 141.007399 190.175046
마포구 118898.006160 1981.802875 121.985298 160.167700
서대문구 82341.297479 1981.615126 134.351227 169.020084
서초구 266996.295000 1977.215000 248.871000 351.464450
성동구 111968.065868 1985.742515 119.319202 170.560878
성북구 62674.463768 1977.394714 127.045098 132.439531
송파구 122192.779412 1988.680147 146.252684 247.870037
양천구 87385.605590 1988.422360 145.861615 227.504627
영등포구 84829.758730 1975.965079 304.477143 158.307254
용산구 131512.383769 1980.195323 116.176080 146.881527
은평구 76228.070028 1980.773109 143.366737 172.915238
종로구 108906.452273 1964.240909 160.897955 142.375341
중구 102544.804714 1973.225589 103.072424 134.709596
중랑구 74283.393839 1988.011001 129.430803 193.037470
In [12]:
plt.figure(figsize=(20,10))
sns.boxplot(x='SiGunGu', y="거래금액(만원)", data=Seoul)
plt.show()
In [13]:
plt.figure(figsize=(20,10))
sns.boxplot(x='SiGunGu', y="거래금액(만원)", data=Seoul)
sns.swarmplot(x='SiGunGu', y="거래금액(만원)", data=Seoul, color=".6")
plt.show()

2. folium을 활용하여 지도에 표현하기

In [16]:
import json
In [17]:
geo_seoul = json.load(open('data/seoul_municipalities_geo_simple.json', encoding='utf-8'))
In [18]:
geo_seoul.keys() # 딕셔너리의 key 정보
Out[18]:
dict_keys(['type', 'features'])
In [19]:
geo_seoul['features'][0]
Out[19]:
{'type': 'Feature',
 'id': '강동구',
 'properties': {'code': '11250',
  'name': '강동구',
  'name_eng': 'Gangdong-gu',
  'base_year': '2013'},
 'geometry': {'type': 'Polygon',
  'coordinates': [[[127.11519584981606, 37.557533180704915],
    [127.16683184366129, 37.57672487388627],
    [127.18408792330152, 37.55814280369575],
    [127.16530984307447, 37.54221851258693],
    [127.14672806823502, 37.51415680680291],
    [127.12123165719615, 37.52528270089],
    [127.1116764203608, 37.540669955324965],
    [127.11519584981606, 37.557533180704915]]]}}
In [20]:
geo_seoul['features'][0]['geometry']['coordinates'][0]
Out[20]:
[[127.11519584981606, 37.557533180704915],
 [127.16683184366129, 37.57672487388627],
 [127.18408792330152, 37.55814280369575],
 [127.16530984307447, 37.54221851258693],
 [127.14672806823502, 37.51415680680291],
 [127.12123165719615, 37.52528270089],
 [127.1116764203608, 37.540669955324965],
 [127.11519584981606, 37.557533180704915]]
In [21]:
len(geo_seoul['features'][0]['geometry']['coordinates'][0])
Out[21]:
8
In [22]:
len(geo_seoul['features'][1]['geometry']['coordinates'][0])
Out[22]:
11
In [23]:
geo_seoul['features'][0]['id'], geo_seoul['features'][0]['properties']['name']
Out[23]:
('강동구', '강동구')
In [24]:
import folium
In [25]:
#folium.Map(location=[48.8667, 2.33333]) # 프랑스 파리
#folium.Map([48.8667, 2.33333]) # 프랑스 파리
#folium.Map(location=[37.56667, 126.97806]) # 대한민국 서울
#folium.Map(location=[37.56667, 126.97806], zoom_start=8) # default 10
#folium.Map(location=[37.56667, 126.97806], min_zoom=11, max_zoom=11) # 위치 고정
folium.Map(location=[37.5502, 126.982], min_zoom=11, max_zoom=11, tiles='Stamen Toner') # 서울시
Out[25]:

서울시 구별 주택 시각화

  • 거래금액
In [27]:
map = folium.Map(location=[37.5502, 126.982], min_zoom=11, max_zoom=11, 
                 tiles='Stamen Toner') # 서울시

map.choropleth(geo_data=geo_seoul,
               data=AveSeoul['거래금액(만원)'],
               columns=[AveSeoul.index, AveSeoul['거래금액(만원)']], # 주의!!
               fill_color='Reds',
               legend_name = '거래금액(만원)',
               key_on='feature.id') # 가능
#               key_on='feature.properties.name') # 가능

map
Out[27]:
In [28]:
map.save('data/map/map_seoul.html')
# 지도 저장하기
  • 연면적
In [29]:
map = folium.Map(location=[37.5502, 126.982], min_zoom=11, max_zoom=11, tiles='Stamen Toner') # 서울시

map.choropleth(geo_data=geo_seoul,
               data=AveSeoul['연면적(㎡)'],
               columns=[AveSeoul.index, AveSeoul['연면적(㎡)']], # 주의!!
               fill_color='Blues',
               legend_name = '연면적(㎡)',
#               key_on='feature.id') # 가능
               key_on='feature.properties.name') # 가능

map
Out[29]:
In [30]:
map.save('data/map/map_seoul_area.html')
  • 건축년도
In [31]:
map = folium.Map(location=[37.5502, 126.982], min_zoom=11, max_zoom=11, tiles='Stamen Toner') # 서울시

map.choropleth(geo_data=geo_seoul,
               data=AveSeoul['건축년도'],
               columns=[AveSeoul.index, AveSeoul['건축년도']], # 주의!!
               fill_color='Purples',
               legend_name = '건축년도',
#               key_on='feature.id') # 가능
               key_on='feature.properties.name') # 가능

map
Out[31]:
In [32]:
map.save('data/map/map_seoul_year.html')

원하는 집 찾기

In [33]:
map_pos = [37.56667, 126.97806] # 서울시

m = folium.Map(map_pos, min_zoom=11, max_zoom=11)

folium.CircleMarker(location = map_pos, radius = 200).add_to(m) # default는 blue

marker_pos = [37.506178, 127.049236] # 서울시 강남구 스땡벅스 선릉역점

folium.Marker(marker_pos).add_to(m) # default는 blue

m
Out[33]:
In [33]:
map_pos = [37.56667, 126.97806] # 서울시

m = folium.Map(map_pos, min_zoom=11, max_zoom=11)

folium.CircleMarker(location = map_pos, radius = 200, color='blue', fill_color='blue').add_to(m) 

marker_pos = [37.506178, 127.049236] # 서울시 강남구 스땡벅스 선릉역점

folium.Marker(marker_pos, popup='스땡벅스 선릉역점').add_to(m) # default는 blue

m
Out[33]:
In [34]:
# radius의 의미 이해하기

map_pos = [37.56667, 126.97806] # 서울시

m = folium.Map(map_pos, min_zoom=11, max_zoom=11)

folium.CircleMarker(location = map_pos, radius = 200, color='blue', fill_color='blue').add_to(m)
folium.CircleMarker(location = map_pos, radius = 100, color='red', fill_color='red').add_to(m)
folium.Circle(location = map_pos, radius = 1000, color='black', fill_color='black').add_to(m) # 단위 : 미터

marker_pos = [37.506178, 127.049236] # 서울시 강남구 스타땡스 선릉역점

folium.Marker(marker_pos, popup='스타땡스 선릉역점').add_to(m)

# https://www.google.co.kr/maps

m
Out[34]:
In [35]:
# radius의 의미 이해하기

map_pos = [37.56667, 126.97806] # 서울시

m = folium.Map(map_pos, min_zoom=10, max_zoom=10)

folium.CircleMarker(location = map_pos, radius = 200, color='blue', 
                    fill_color='blue').add_to(m)
folium.CircleMarker(location = map_pos, radius = 100, color='red', 
                    fill_color='red').add_to(m)
folium.Circle(location = map_pos, radius = 1000, color='black', 
              fill_color='black').add_to(m) # 단위 : 미터
 
marker_pos = [37.506178, 127.049236] # 서울시 강남구 스타땡스 선릉역점

folium.Marker(marker_pos, popup='스타땡스 선릉역점').add_to(m) # default는 blue

m
Out[35]:

문제 : 2018년 이후에 건축되었고 주택유형이 '단독'이면서 100000(만원) 미만의 주택 찾기

In [36]:
House1 = Seoul[Seoul['건축년도'] > 2017]
House2 = House1[House1['주택유형']=='단독']
House = House2[House2['거래금액(만원)']<100000] # 10억 미만
House
Out[36]:
시군구 주택유형 연면적(㎡) 대지면적(㎡) 거래금액(만원) 건축년도 SiDo SiGunGu ID
4347 서울특별시 강북구 번동 단독 199.60 93.6 95450 2018 서울특별시 강북구 서울 강북
5374 서울특별시 중구 신당동 단독 49.59 57.0 26500 2018 서울특별시 중구 서울 중구
6301 서울특별시 성북구 정릉동 단독 149.78 102.0 82000 2018 서울특별시 성북구 서울 성북
12594 서울특별시 중랑구 면목동 단독 122.96 74.8 66000 2018 서울특별시 중랑구 서울 중랑
In [37]:
House.reset_index(inplace=True, drop=True)
House
Out[37]:
시군구 주택유형 연면적(㎡) 대지면적(㎡) 거래금액(만원) 건축년도 SiDo SiGunGu ID
0 서울특별시 강북구 번동 단독 199.60 93.6 95450 2018 서울특별시 강북구 서울 강북
1 서울특별시 중구 신당동 단독 49.59 57.0 26500 2018 서울특별시 중구 서울 중구
2 서울특별시 성북구 정릉동 단독 149.78 102.0 82000 2018 서울특별시 성북구 서울 성북
3 서울특별시 중랑구 면목동 단독 122.96 74.8 66000 2018 서울특별시 중랑구 서울 중랑
In [38]:
marker_pos1 = [37.632145, 127.036528] # 강북구 번2동 번동중학교
marker_pos2 = [37.560220, 127.013759] # 중구 신당동 청구역
marker_pos3 = [37.608858, 127.001017] # 성북구 정릉동 고려대학교
marker_pos4 = [37.585363, 127.086666] # 중랑구 면목동 면동초등학교
In [39]:
target_pos = [37.610714, 127.021700] # 서울미아초등학교
# 서울특별시 성북구 길음1동 삼양로 77

m = folium.Map(target_pos, min_zoom=12, max_zoom=12)

folium.Circle(location = target_pos, radius = 5000, 
              color='red', fill_color='red').add_to(m) # 반경 5km
folium.CircleMarker(location = marker_pos1, radius = House['거래금액(만원)'][0]/5000, 
                    color='blue', fill_color='blue').add_to(m)
folium.CircleMarker(location = marker_pos2, radius = House['거래금액(만원)'][1]/5000, 
                    color='blue', fill_color='blue').add_to(m)
folium.CircleMarker(location = marker_pos3, radius = House['거래금액(만원)'][2]/5000, 
                    color='blue', fill_color='blue').add_to(m)
folium.CircleMarker(location = marker_pos4, radius = House['거래금액(만원)'][3]/5000, 
                    color='blue', fill_color='blue').add_to(m)

folium.Marker(target_pos, popup='서울 미아초등학교', 
              icon=folium.Icon(color='red')).add_to(m)
folium.Marker(marker_pos1, popup='집1').add_to(m)
folium.Marker(marker_pos2, popup='집2').add_to(m)
folium.Marker(marker_pos3, popup='집3').add_to(m)
folium.Marker(marker_pos4, popup='집4').add_to(m)

m
Out[39]:
In [40]:
m.save('data/map/map_seoul_house.html')

전국 지도 버전

In [41]:
geo_korea = json.load(open('data/skorea_municipalities_geo_simple.json', encoding='utf-8'))
In [42]:
geo_korea.keys()
Out[42]:
dict_keys(['type', 'features'])
In [43]:
geo_korea['features'][230] # 전국 지도
Out[43]:
{'type': 'Feature',
 'id': '서울 관악',
 'properties': {'code': '11210',
  'name': '관악구',
  'name_eng': 'Gwanak-gu',
  'base_year': '2013'},
 'geometry': {'type': 'Polygon',
  'coordinates': [[[126.98367668291802, 37.473856492692086],
    [126.99072073195462, 37.455326143310025],
    [126.96520439085143, 37.438249784006246],
    [126.95000001010182, 37.43613451165719],
    [126.93084408056525, 37.447382928333994],
    [126.9167728146601, 37.45490566423789],
    [126.90156094129895, 37.47753842789901],
    [126.90531975801812, 37.48218087575429],
    [126.94922661389508, 37.49125437495649],
    [126.9725891850662, 37.472561363278125],
    [126.98367668291802, 37.473856492692086]]]}}
In [44]:
geo_seoul['features'][4] # 서울시 지도
Out[44]:
{'type': 'Feature',
 'id': '관악구',
 'properties': {'code': '11210',
  'name': '관악구',
  'name_eng': 'Gwanak-gu',
  'base_year': '2013',
  'style': {'weight': 1,
   'opacity': 1,
   'color': 'black',
   'fillOpacity': 0.6,
   'fillColor': '#54278f'},
  'highlight': {}},
 'geometry': {'type': 'Polygon',
  'coordinates': [[[126.98367668291802, 37.473856492692086],
    [126.99072073195462, 37.455326143310025],
    [126.96520439085143, 37.438249784006246],
    [126.95000001010182, 37.43613451165719],
    [126.93084408056525, 37.447382928333994],
    [126.9167728146601, 37.45490566423789],
    [126.90156094129895, 37.47753842789901],
    [126.90531975801812, 37.48218087575429],
    [126.94922661389508, 37.49125437495649],
    [126.9725891850662, 37.472561363278125],
    [126.98367668291802, 37.473856492692086]]]}}
In [45]:
geo_korea['features'][230]['id'], geo_korea['features'][230]['properties']['name']
Out[45]:
('서울 관악', '관악구')
In [46]:
geo_seoul['features'][4]['id'], geo_seoul['features'][4]['properties']['name']
Out[46]:
('관악구', '관악구')
In [47]:
AveSeoul.index
Out[47]:
Index(['강남구', '강동구', '강북구', '강서구', '관악구', '광진구', '구로구', '금천구', '노원구', '도봉구',
       '동대문구', '동작구', '마포구', '서대문구', '서초구', '성동구', '성북구', '송파구', '양천구', '영등포구',
       '용산구', '은평구', '종로구', '중구', '중랑구'],
      dtype='object', name='SiGunGu')
In [49]:
map = folium.Map(location=[37.5502, 126.982], zoom_start=11, tiles='Stamen Toner')

map.choropleth(geo_data=geo_korea,
               data=AveSeoul['거래금액(만원)'],
               columns=[AveSeoul.index, AveSeoul['거래금액(만원)']], # 주의!!
               fill_color='Reds',
               key_on='feature.properties.name') # 주의!!
#               key_on='feature.id') # 표시되지 않음
map
Out[49]:
In [50]:
map.save('data/map/map_seoul_korea.html')

3. 연습문제 : 부산광역시

  • 부산광역시 구별 주택 거래금액 시각화
  • 2001년 이후에 건축되었고 '다가구'이면서 가격 50000(만원) 미만의 집 찾기.
    • 단, 나의 직장인 금정구 '서곡초등학교' 반경 6km 이내에 있으면서 '사직 야구장'과 가까운 집을 원함.
In [51]:
df[df['SiGunGu'] == '중구']
# 중복 주의
Out[51]:
시군구 주택유형 연면적(㎡) 대지면적(㎡) 거래금액(만원) 건축년도 SiDo SiGunGu ID
3578 대구광역시 중구 계산동1가 단독 39.41 52.90 6000 1950 대구광역시 중구 대구 중구
3579 대구광역시 중구 남산동 단독 21.78 40.00 13000 1950 대구광역시 중구 대구 중구
3580 대구광역시 중구 남산동 단독 36.03 76.00 7000 1949 대구광역시 중구 대구 중구
3581 대구광역시 중구 남산동 단독 23.80 81.00 16400 1950 대구광역시 중구 대구 중구
3582 대구광역시 중구 남산동 단독 67.62 93.00 35100 1983 대구광역시 중구 대구 중구
3583 대구광역시 중구 남산동 단독 98.36 100.00 32546 2000 대구광역시 중구 대구 중구
3584 대구광역시 중구 남산동 단독 49.22 105.00 26450 1949 대구광역시 중구 대구 중구
3585 대구광역시 중구 남산동 단독 244.59 109.00 27500 1994 대구광역시 중구 대구 중구
3586 대구광역시 중구 남산동 단독 111.29 126.00 22950 1993 대구광역시 중구 대구 중구
3587 대구광역시 중구 남산동 단독 263.06 146.50 80500 2018 대구광역시 중구 대구 중구
3588 대구광역시 중구 남산동 단독 72.07 160.30 15750 1974 대구광역시 중구 대구 중구
3589 대구광역시 중구 남산동 단독 443.73 240.00 58000 2002 대구광역시 중구 대구 중구
3590 대구광역시 중구 달성동 단독 23.85 49.60 13900 2001 대구광역시 중구 대구 중구
3591 대구광역시 중구 달성동 단독 23.60 64.10 18150 1949 대구광역시 중구 대구 중구
3592 대구광역시 중구 달성동 단독 80.28 72.70 19850 1993 대구광역시 중구 대구 중구
3593 대구광역시 중구 대봉동 단독 35.70 93.00 15000 1959 대구광역시 중구 대구 중구
3594 대구광역시 중구 대신동 단독 186.58 254.00 63000 1972 대구광역시 중구 대구 중구
3595 대구광역시 중구 동산동 단독 182.80 142.00 75000 2017 대구광역시 중구 대구 중구
3596 대구광역시 중구 동인동2가 단독 57.75 132.20 35000 1984 대구광역시 중구 대구 중구
3597 대구광역시 중구 동인동3가 단독 30.57 88.80 9982 1950 대구광역시 중구 대구 중구
3598 대구광역시 중구 동인동3가 단독 427.91 201.30 52000 2003 대구광역시 중구 대구 중구
3599 대구광역시 중구 동인동4가 단독 69.69 167.30 35000 1950 대구광역시 중구 대구 중구
3600 대구광역시 중구 봉산동 단독 16.53 40.00 8000 1950 대구광역시 중구 대구 중구
3601 대구광역시 중구 봉산동 단독 41.59 49.00 20000 1949 대구광역시 중구 대구 중구
3602 대구광역시 중구 봉산동 단독 60.17 128.90 85000 1968 대구광역시 중구 대구 중구
3603 대구광역시 중구 삼덕동1가 단독 29.72 57.90 80300 1949 대구광역시 중구 대구 중구
3604 대구광역시 중구 삼덕동1가 단독 36.89 82.60 13200 1952 대구광역시 중구 대구 중구
3605 대구광역시 중구 삼덕동2가 단독 48.76 246.20 100000 1949 대구광역시 중구 대구 중구
3606 대구광역시 중구 삼덕동2가 단독 494.22 275.60 139500 2013 대구광역시 중구 대구 중구
3607 대구광역시 중구 삼덕동3가 단독 52.99 133.20 23500 1968 대구광역시 중구 대구 중구
... ... ... ... ... ... ... ... ... ...
91215 부산광역시 중구 영주동 단독 174.31 126.60 20450 1974 부산광역시 중구 부산 중구
91216 부산광역시 중구 영주동 단독 149.15 164.30 31000 1978 부산광역시 중구 부산 중구
91626 서울특별시 중구 광희동2가 단독 81.28 92.60 120000 1961 서울특별시 중구 서울 중구
91627 서울특별시 중구 만리동1가 다가구 86.84 62.60 88500 1997 서울특별시 중구 서울 중구
91628 서울특별시 중구 신당동 다가구 149.34 82.62 90000 2000 서울특별시 중구 서울 중구
91629 서울특별시 중구 신당동 단독 81.00 23.00 13000 1990 서울특별시 중구 서울 중구
91630 서울특별시 중구 신당동 단독 15.21 26.00 27500 1928 서울특별시 중구 서울 중구
91631 서울특별시 중구 신당동 단독 15.21 43.00 36750 1928 서울특별시 중구 서울 중구
91632 서울특별시 중구 신당동 단독 282.03 179.00 137500 1984 서울특별시 중구 서울 중구
91633 서울특별시 중구 신당동 단독 485.92 252.00 95000 1988 서울특별시 중구 서울 중구
91634 서울특별시 중구 입정동 단독 56.29 85.00 160000 1980 서울특별시 중구 서울 중구
91635 서울특별시 중구 중림동 단독 182.28 150.50 140000 1979 서울특별시 중구 서울 중구
91727 울산광역시 중구 교동 단독 83.47 89.00 7000 1971 울산광역시 중구 울산 중구
91728 울산광역시 중구 남외동 단독 255.00 142.00 39500 2016 울산광역시 중구 울산 중구
91729 울산광역시 중구 다운동 단독 193.96 175.60 30050 1993 울산광역시 중구 울산 중구
91730 울산광역시 중구 복산동 단독 117.51 116.00 28000 1995 울산광역시 중구 울산 중구
91731 울산광역시 중구 우정동 단독 82.80 69.10 13000 1981 울산광역시 중구 울산 중구
91732 울산광역시 중구 우정동 단독 131.46 115.00 39000 1985 울산광역시 중구 울산 중구
91733 울산광역시 중구 우정동 단독 131.26 181.30 51000 1979 울산광역시 중구 울산 중구
91734 울산광역시 중구 태화동 단독 328.26 189.10 67800 1996 울산광역시 중구 울산 중구
91735 울산광역시 중구 학산동 단독 74.59 35.00 24000 1984 울산광역시 중구 울산 중구
91736 울산광역시 중구 학성동 단독 82.81 206.30 17000 1974 울산광역시 중구 울산 중구
91868 인천광역시 중구 운남동 다가구 448.45 301.10 116000 2017 인천광역시 중구 인천 중구
91869 인천광역시 중구 운남동 단독 85.32 431.00 36000 2007 인천광역시 중구 인천 중구
91870 인천광역시 중구 운남동 단독 110.76 577.00 33600 2009 인천광역시 중구 인천 중구
91871 인천광역시 중구 운북동 단독 99.27 535.00 36550 2010 인천광역시 중구 인천 중구
91872 인천광역시 중구 을왕동 단독 86.94 432.00 39000 1969 인천광역시 중구 인천 중구
91873 인천광역시 중구 전동 단독 40.18 168.10 27600 1985 인천광역시 중구 인천 중구
91874 인천광역시 중구 중산동 다가구 605.46 412.10 140157 2017 인천광역시 중구 인천 중구
91875 인천광역시 중구 중산동 단독 43.89 232.00 17920 2009 인천광역시 중구 인천 중구

2004 rows × 9 columns

In [52]:
Busan = df[df['SiDo'] == '부산광역시']
Busan.head()
Out[52]:
시군구 주택유형 연면적(㎡) 대지면적(㎡) 거래금액(만원) 건축년도 SiDo SiGunGu ID
3853 부산광역시 강서구 강동동 단독 45.95 111.0 13750 2018 부산광역시 강서구 부산 강서
3854 부산광역시 강서구 강동동 단독 52.89 337.0 28000 1931 부산광역시 강서구 부산 강서
3855 부산광역시 강서구 눌차동 단독 49.50 152.0 9000 2012 부산광역시 강서구 부산 강서
3856 부산광역시 강서구 대저1동 단독 54.88 172.0 38700 1968 부산광역시 강서구 부산 강서
3857 부산광역시 강서구 대저1동 단독 60.83 202.0 43000 1969 부산광역시 강서구 부산 강서
In [53]:
Busan.reset_index(inplace=True, drop=True)
Busan.head()
Out[53]:
시군구 주택유형 연면적(㎡) 대지면적(㎡) 거래금액(만원) 건축년도 SiDo SiGunGu ID
0 부산광역시 강서구 강동동 단독 45.95 111.0 13750 2018 부산광역시 강서구 부산 강서
1 부산광역시 강서구 강동동 단독 52.89 337.0 28000 1931 부산광역시 강서구 부산 강서
2 부산광역시 강서구 눌차동 단독 49.50 152.0 9000 2012 부산광역시 강서구 부산 강서
3 부산광역시 강서구 대저1동 단독 54.88 172.0 38700 1968 부산광역시 강서구 부산 강서
4 부산광역시 강서구 대저1동 단독 60.83 202.0 43000 1969 부산광역시 강서구 부산 강서
In [54]:
Busan['SiGunGu'].unique()
Out[54]:
array(['강서구', '금정구', '기장군', '남구', '동구', '동래구', '부산진구', '북구', '사상구', '사하구',
       '서구', '수영구', '연제구', '영도구', '중구', '해운대구'], dtype=object)
In [55]:
Seoul['SiGunGu'].unique()
Out[55]:
array(['강남구', '강동구', '강북구', '강서구', '관악구', '광진구', '구로구', '금천구', '노원구',
       '도봉구', '동대문구', '동작구', '마포구', '서대문구', '서초구', '성동구', '성북구', '송파구',
       '양천구', '영등포구', '용산구', '은평구', '종로구', '중구', '중랑구'], dtype=object)
In [56]:
Busan['ID'].unique()
Out[56]:
array(['부산 강서', '부산 금정', '부산 기장', '부산 남구', '부산 동구', '부산 동래', '부산 부산진',
       '부산 북구', '부산 사상', '부산 사하', '부산 서구', '부산 수영', '부산 연제', '부산 영도',
       '부산 중구', '부산 해운대'], dtype=object)
In [57]:
AveBusan = pd.pivot_table(Busan, index=['ID']) # ID를 index로.. (전국에 표시해야 하므로..)
AveBusan
Out[57]:
거래금액(만원) 건축년도 대지면적(㎡) 연면적(㎡)
ID
부산 강서 41765.944882 1987.811024 277.887717 136.874803
부산 금정 32542.918103 1985.077586 131.125711 127.010690
부산 기장 48133.764045 1987.387640 286.917697 155.989045
부산 남구 24477.769337 1979.055249 109.715622 86.437776
부산 동구 18429.744131 1955.136150 77.811620 78.055540
부산 동래 49407.116327 1981.004082 158.504980 132.802204
부산 부산진 31493.924242 1977.418561 105.772528 92.616061
부산 북구 33649.537445 1982.449339 148.692070 160.440352
부산 사상 29564.960993 1982.248227 140.662695 138.886383
부산 사하 22212.353556 1984.502092 113.250146 125.290063
부산 서구 18878.209790 1971.440559 97.688951 90.041049
부산 수영 46743.611888 1980.895105 154.437517 131.827378
부산 연제 39549.667656 1973.676558 129.960593 117.796291
부산 영도 14253.562814 1982.924623 96.298116 80.902588
부산 중구 28427.019417 1966.825243 94.826408 138.549320
부산 해운대 34376.516216 1986.186486 95.510568 119.330243
In [58]:
plt.figure(figsize=(20,10))
sns.boxplot(x='ID', y="거래금액(만원)", data=Busan)
plt.show()
In [59]:
plt.figure(figsize=(20,10))
sns.boxplot(x='ID', y="거래금액(만원)", data=Busan)
sns.swarmplot(x='ID', y="거래금액(만원)", data=Busan, color=".6")
plt.show()
In [60]:
geo_korea['features'][220]
Out[60]:
{'type': 'Feature',
 'id': '부산 동래',
 'properties': {'code': '21060',
  'name': '동래구',
  'name_eng': 'Dongnae-gu',
  'base_year': '2013',
  'style': {'weight': 1,
   'opacity': 1,
   'color': 'black',
   'fillOpacity': 0.6,
   'fillColor': 'black'},
  'highlight': {}},
 'geometry': {'type': 'Polygon',
  'coordinates': [[[129.06246127125198, 35.22314656458455],
    [129.07996846697185, 35.223190926035926],
    [129.11230628758815, 35.20703612721303],
    [129.1177825437272, 35.18474986968091],
    [129.11742196747971, 35.1801022299339],
    [129.08258984394146, 35.19618777329709],
    [129.04994737431633, 35.19112585048916],
    [129.04612823614372, 35.195308829813435],
    [129.06246127125198, 35.22314656458455]]]}}
In [61]:
geo_korea['features'][220]['id'], geo_korea['features'][220]['properties']['name']
Out[61]:
('부산 동래', '동래구')
In [62]:
map = folium.Map(location=[35.17944, 129.07556], min_zoom=10, max_zoom=10, 
                 tiles='Stamen Toner') # 부산광역시

map.choropleth(geo_data=geo_korea,
               data=AveBusan['거래금액(만원)'],
               columns=[AveBusan.index, AveBusan['거래금액(만원)']], # 주의!! DataFrame.index만 적용 가능함
               fill_color='Greens',
               legend_name = '거래금액(만원)',
               key_on='feature.id')
#               key_on='feature.properties.name') # 나타나지 않음
map
Out[62]:
In [63]:
map.save('data/map/map_busan.html')
In [64]:
House1 = Busan[Busan['건축년도'] > 2000]
House2 = House1[House1['주택유형']=='다가구']
House = House2[House2['거래금액(만원)']<50000]
House
Out[64]:
시군구 주택유형 연면적(㎡) 대지면적(㎡) 거래금액(만원) 건축년도 SiDo SiGunGu ID
1249 부산광역시 남구 감만동 다가구 256.80 112.00 35000 2014 부산광역시 남구 부산 남구
1863 부산광역시 해운대구 반송동 다가구 130.68 50.00 12500 2001 부산광역시 해운대구 부산 해운대
2201 부산광역시 북구 구포동 다가구 85.77 108.00 20000 2002 부산광역시 북구 부산 북구
4060 부산광역시 수영구 수영동 다가구 140.56 168.20 34000 2017 부산광역시 수영구 부산 수영
4477 부산광역시 사하구 다대동 다가구 177.40 51.67 29000 2004 부산광역시 사하구 부산 사하
5472 부산광역시 해운대구 반송동 다가구 123.70 50.00 7750 2001 부산광역시 해운대구 부산 해운대
5714 부산광역시 북구 덕천동 다가구 252.26 205.90 48000 2003 부산광역시 북구 부산 북구
5996 부산광역시 동구 초량동 다가구 127.11 72.00 19500 2002 부산광역시 동구 부산 동구
6128 부산광역시 서구 아미동2가 다가구 50.01 49.60 9500 2015 부산광역시 서구 부산 서구
In [65]:
House.reset_index(inplace=True, drop=True)
House
Out[65]:
시군구 주택유형 연면적(㎡) 대지면적(㎡) 거래금액(만원) 건축년도 SiDo SiGunGu ID
0 부산광역시 남구 감만동 다가구 256.80 112.00 35000 2014 부산광역시 남구 부산 남구
1 부산광역시 해운대구 반송동 다가구 130.68 50.00 12500 2001 부산광역시 해운대구 부산 해운대
2 부산광역시 북구 구포동 다가구 85.77 108.00 20000 2002 부산광역시 북구 부산 북구
3 부산광역시 수영구 수영동 다가구 140.56 168.20 34000 2017 부산광역시 수영구 부산 수영
4 부산광역시 사하구 다대동 다가구 177.40 51.67 29000 2004 부산광역시 사하구 부산 사하
5 부산광역시 해운대구 반송동 다가구 123.70 50.00 7750 2001 부산광역시 해운대구 부산 해운대
6 부산광역시 북구 덕천동 다가구 252.26 205.90 48000 2003 부산광역시 북구 부산 북구
7 부산광역시 동구 초량동 다가구 127.11 72.00 19500 2002 부산광역시 동구 부산 동구
8 부산광역시 서구 아미동2가 다가구 50.01 49.60 9500 2015 부산광역시 서구 부산 서구
In [66]:
marker_pos = [
    [35.114992, 129.082752], # 남구 감만동 동항초등학교
    [35.228946, 129.157009], # 해운대구 반송동 송운초등학교
    [35.196538, 129.008752], # 북구 구포동 포천초등학교
    [35.170736, 129.115990], # 수영구 수영동 주민센터
    [35.069483, 128.979623], # 사하구 다대동 다송초등학교
    [35.233308, 129.147999], # 해운대구 반송동 동부산대학교
    [35.214680, 129.011909], # 북구 덕천동 덕천중학교
    [35.121655, 129.036808], # 동구 동구 초량동 부산고등학교
    [35.098581, 129.015987]] # 서구 아미동 아미초등학교
marker_pos
Out[66]:
[[35.114992, 129.082752],
 [35.228946, 129.157009],
 [35.196538, 129.008752],
 [35.170736, 129.11599],
 [35.069483, 128.979623],
 [35.233308, 129.147999],
 [35.21468, 129.011909],
 [35.121655, 129.036808],
 [35.098581, 129.015987]]
In [67]:
target_pos = [35.220730, 129.104888] # 금정구 서곡초등학교
baseball_pos = [35.195578, 129.061319] # 동래구 사직 야구장

m = folium.Map(target_pos, min_zoom=11, max_zoom=11)

folium.Circle(location = target_pos, radius = 6000, color='red', fill_color='red').add_to(m) # 반경 6km
folium.Circle(location = baseball_pos, radius = 6000, color='yellow', fill_color='black').add_to(m) # 반경 6km

for n in range(len(marker_pos)):
    folium.CircleMarker(location = marker_pos[n], 
                        radius = House['거래금액(만원)'][n]/3000, 
                        color='blue', fill_color='blue').add_to(m)
    
folium.Marker(target_pos, popup='서곡초등학교', icon=folium.Icon(color='red')).add_to(m)
folium.Marker(baseball_pos, popup='야구장', icon=folium.Icon(color='black')).add_to(m)
folium.Marker(marker_pos[0], popup='1번 집').add_to(m)
folium.Marker(marker_pos[1], popup='2번 집').add_to(m)
folium.Marker(marker_pos[2], popup='3번 집').add_to(m)
folium.Marker(marker_pos[3], popup='4번 집').add_to(m)
folium.Marker(marker_pos[4], popup='5번 집').add_to(m)
folium.Marker(marker_pos[5], popup='6번 집').add_to(m)
folium.Marker(marker_pos[6], popup='7번 집').add_to(m)
folium.Marker(marker_pos[7], popup='8번 집').add_to(m)
folium.Marker(marker_pos[8], popup='9번 집').add_to(m)

m
Out[67]:
In [68]:
m.save('data/map/map_busan_house.html')

4. 참고

SiGunGu를 index로 하면 어떻게 될까요?

  • 부산광역시
In [69]:
AveBusan0 = pd.pivot_table(Busan, index=['SiGunGu']) 
AveBusan0
Out[69]:
거래금액(만원) 건축년도 대지면적(㎡) 연면적(㎡)
SiGunGu
강서구 41765.944882 1987.811024 277.887717 136.874803
금정구 32542.918103 1985.077586 131.125711 127.010690
기장군 48133.764045 1987.387640 286.917697 155.989045
남구 24477.769337 1979.055249 109.715622 86.437776
동구 18429.744131 1955.136150 77.811620 78.055540
동래구 49407.116327 1981.004082 158.504980 132.802204
부산진구 31493.924242 1977.418561 105.772528 92.616061
북구 33649.537445 1982.449339 148.692070 160.440352
사상구 29564.960993 1982.248227 140.662695 138.886383
사하구 22212.353556 1984.502092 113.250146 125.290063
서구 18878.209790 1971.440559 97.688951 90.041049
수영구 46743.611888 1980.895105 154.437517 131.827378
연제구 39549.667656 1973.676558 129.960593 117.796291
영도구 14253.562814 1982.924623 96.298116 80.902588
중구 28427.019417 1966.825243 94.826408 138.549320
해운대구 34376.516216 1986.186486 95.510568 119.330243
In [70]:
geo_korea['features'][220]['id'], geo_korea['features'][220]['properties']['name']
Out[70]:
('부산 동래', '동래구')
In [71]:
map = folium.Map(location=[35.17944, 129.07556], min_zoom=11, max_zoom=11, tiles='Stamen Toner') # 부산광역시

map.choropleth(geo_data=geo_korea,
               data=AveBusan0['거래금액(만원)'],
               columns=[AveBusan0.index, AveBusan0['거래금액(만원)']],
               fill_color='Greens',
               key_on='feature.properties.name')

map # 흰색과 검정색 영역의 의미?
Out[71]:
In [72]:
map = folium.Map(location=[35.17944, 129.07556], min_zoom=7, max_zoom=7, tiles='Stamen Toner') # 부산광역시

map.choropleth(geo_data=geo_korea,
               data=AveBusan0['거래금액(만원)'],
               columns=[AveBusan0.index, AveBusan0['거래금액(만원)']],
               fill_color='Greens',
               legend_name = '거래금액(만원)',
               key_on='feature.properties.name')

map # 흰색과 검정색 영역의 의미?
Out[72]:
In [73]:
map.save('data/map/map_busan_korea_error.html')
  • 전국 평균 주택 거래금액
In [74]:
AveKorea = pd.pivot_table(df, index=['ID'])
AveKorea
Out[74]:
거래금액(만원) 건축년도 대지면적(㎡) 연면적(㎡)
ID
가평 28162.674286 1993.837143 542.871829 133.077086
강릉 23818.381107 1989.428339 335.189446 153.665879
강진 5106.300000 1976.038889 490.971333 88.894722
거제 26270.153310 1994.390244 351.264077 137.072997
거창 14597.135266 1981.589372 303.983043 107.744010
경산 36170.133621 1990.950431 284.119871 206.705431
경주 26066.193646 1984.708018 373.503918 134.416384
계룡 38529.411765 1998.705882 397.302941 245.700882
고령 14642.963768 1982.920290 439.892899 126.779565
고성 11868.088571 1983.588571 371.603400 91.252800
고양 덕양 73915.038023 1969.692015 267.276046 213.578137
고양 일산동 90471.648352 2000.747253 302.754066 301.319451
고양 일산서 70287.671875 1998.890625 304.126562 254.453594
고창 8876.873096 1988.076142 513.034213 96.699340
고흥 5662.173780 1973.743902 549.495488 88.076982
곡성 8106.056911 1985.146341 452.957724 110.941138
공주 16790.643963 1988.730650 433.787771 117.418421
과천 150887.850000 1989.900000 251.640000 231.964000
광명 66888.589744 1986.072650 154.113205 194.168846
광양 20996.564972 1993.242938 334.407345 169.199040
광주 51994.038567 2003.280992 412.617080 204.009394
광주 광산 37874.819964 1988.179144 226.740152 173.054073
광주 남구 23286.038986 1979.769981 163.438450 118.267427
광주 동구 24773.940678 1976.802260 153.813616 113.746780
광주 북구 26856.761258 1983.858112 171.796527 162.281573
광주 서구 38267.720430 1990.552688 195.758290 207.976774
괴산 13702.779661 1990.141243 534.963842 111.883672
구례 10302.516949 1982.423729 445.972881 90.789068
구리 63378.921788 1986.162011 156.235754 213.301732
구미 38319.567515 1998.334638 284.456008 311.569941
... ... ... ... ...
청양 9099.674157 1975.865169 649.582360 86.347640
청주 상당 24577.047337 1988.038462 290.670414 182.606006
청주 서원 34155.516216 1992.672973 301.419595 235.446486
청주 청원 34098.588529 1995.645885 293.590000 230.006584
청주 흥덕 44902.535448 1998.429104 265.009384 292.550970
춘천 35207.979398 1993.234548 299.069540 207.341157
충주 21167.551308 1993.464789 436.893340 160.492153
칠곡 33346.704626 1996.736655 424.990747 254.095587
태백 9525.959184 1987.581633 203.227857 96.268571
태안 17982.311111 1998.648889 533.544622 124.314578
통영 14769.561497 1980.411765 230.139385 99.808209
파주 44198.642447 1994.998088 389.859866 182.890382
평창 14403.765799 2001.914498 541.221561 106.345725
평택 58234.181126 1996.984779 335.991553 233.468387
포천 22587.318182 1998.399351 517.482338 142.000455
포항 남 23594.135659 1984.149225 285.755039 158.226066
포항 북 24311.525157 1996.792453 332.032516 150.459591
하남 82850.668508 1999.756906 239.404696 213.767017
하동 9833.857143 1981.158730 406.722751 89.397302
함안 13157.076471 1992.941176 356.382529 94.126529
함양 12348.873494 1983.000000 399.955060 98.424578
함평 7595.248276 1987.048276 516.957241 88.177310
합천 7815.670270 1978.416216 356.737622 86.140865
해남 6004.756098 1978.268293 460.873984 83.739431
홍성 12136.752294 1998.958716 571.623211 116.820550
홍천 18097.194539 2000.061433 519.656485 119.094130
화성 51163.579585 2002.129758 454.460138 221.804412
화순 13370.593443 1984.032787 398.366262 94.502754
화천 11592.241935 1963.258065 527.211290 105.266452
횡성 15830.532710 2001.455607 573.095794 104.704650

249 rows × 4 columns

In [75]:
AveKorea[AveKorea.index == '고성']
Out[75]:
거래금액(만원) 건축년도 대지면적(㎡) 연면적(㎡)
ID
고성 11868.088571 1983.588571 371.6034 91.2528
In [77]:
#map = folium.Map(location=[36.775356, 127.802357],  min_zoom=7, max_zoom=7, 
#                 tiles='Stamen Toner') # 충청북도 괴산군 문광면
map = folium.Map(location=[36.775356, 127.802357],  zoom_start=7,
                 tiles='Stamen Toner') # 충청북도 괴산군 문광면

map.choropleth(geo_data=geo_korea,
               data=AveKorea['거래금액(만원)'],
               columns=[AveKorea.index, AveKorea['거래금액(만원)']], # 주의!!
               fill_color='YlGnBu',
               legend_name = '거래금액(만원)',
#               key_on='feature.properties.name') # 주의!!
               key_on='feature.id') # 표시되지 않음
map

# (예) 검정색 영역 중 '고성' ---> json 파일에서 고성(경남), 고성(강원)
# 과제 : 오류 수정!!!
Out[77]:
In [78]:
map.save('data/map/map_korea.html')
  • 영역 설정 오류 해결
In [79]:
geo_korea_id = []

for k_id in geo_korea['features']:
    geo_korea_id.append(k_id['id'])
In [81]:
geo_korea_id = pd.DataFrame(geo_korea_id, columns=['ID'])
geo_korea_id.head()
Out[81]:
ID
0 서귀포
1 제주
2 합천
3 거창
4 함양
In [82]:
AveKorea.index
Out[82]:
Index(['가평', '강릉', '강진', '거제', '거창', '경산', '경주', '계룡', '고령', '고성',
       ...
       '함양', '함평', '합천', '해남', '홍성', '홍천', '화성', '화순', '화천', '횡성'],
      dtype='object', name='ID', length=249)
In [83]:
set(geo_korea_id['ID'].unique()) - set(AveKorea.index.unique())
Out[83]:
{'고성(강원)',
 '고성(경남)',
 '부천 소사',
 '부천 오정',
 '부천 원미',
 '인천 남구',
 '창원 합포',
 '창원 회원',
 '포항 남구',
 '포항 북구'}
In [84]:
set(AveKorea.index.unique()) - set(geo_korea_id['ID'].unique()) 
Out[84]:
{'고성', '부천', '인천 미추홀', '창원 마산합포', '창원 마산회원', '청주 서원', '포항 남', '포항 북'}
  • 위 오류 수정은 과제로 남김니다... ^^

bokeh.palettes

- 주의 : json 파일 마다 다르게 설정될 수 있으니 항상 체크!!

내가 원하는 집의 정보를 표현하기

In [85]:
marker_pos0 = [
    [35.114992, 129.082752, '1번: 비싸지만 넓고 최근에 지은 집'], # 남구 감만동 동항초등학교
    [35.228946, 129.157009, '2번: 적절한 면적과 가격의 집'], # 해운대구 반송동 송운초등학교
    [35.196538, 129.008752, '3번: 좁은데 저렴하지도 않고 오래된 집ㅜ_ㅜ;'], # 북구 구포동 포천초등학교
    [35.170736, 129.115990, '4번: 비싸지만 새로 지은 집'], # 수영구 수영동 주민센터
    [35.069483, 128.979623, '5번: 적당한 크기에 조금 오래된 다소 비싼 집'], # 사하구 다대동 다송초등학교
    [35.233308, 129.147999, '6번: 오래 되었지만 적당한 크기의 싼 집'], # 해운대구 반송동 동부산대학교
    [35.214680, 129.011909, '7번: 넓지만 오래되었고 비싼 집'], # 북구 덕천동 덕천중학교
    [35.121655, 129.036808, '8번: 오래 되었지만 적절한 가격의 집'], # 동구 동구 초량동 부산고등학교
    [35.098581, 129.015987, '9번: 좁지만 최근에 지었고 싼 집']] # 서구 아미동 아미초등학교
marker_pos0
Out[85]:
[[35.114992, 129.082752, '1번: 비싸지만 넓고 최근에 지은 집'],
 [35.228946, 129.157009, '2번: 적절한 면적과 가격의 집'],
 [35.196538, 129.008752, '3번: 좁은데 저렴하지도 않고 오래된 집ㅜ_ㅜ;'],
 [35.170736, 129.11599, '4번: 비싸지만 새로 지은 집'],
 [35.069483, 128.979623, '5번: 적당한 크기에 조금 오래된 다소 비싼 집'],
 [35.233308, 129.147999, '6번: 오래 되었지만 적당한 크기의 싼 집'],
 [35.21468, 129.011909, '7번: 넓지만 오래되었고 비싼 집'],
 [35.121655, 129.036808, '8번: 오래 되었지만 적절한 가격의 집'],
 [35.098581, 129.015987, '9번: 좁지만 최근에 지었고 싼 집']]
In [86]:
marker_posA = pd.DataFrame(marker_pos0, columns = ["위도", "경도", "집 정보"])
marker_posA
Out[86]:
위도 경도 집 정보
0 35.114992 129.082752 1번: 비싸지만 넓고 최근에 지은 집
1 35.228946 129.157009 2번: 적절한 면적과 가격의 집
2 35.196538 129.008752 3번: 좁은데 저렴하지도 않고 오래된 집ㅜ_ㅜ;
3 35.170736 129.115990 4번: 비싸지만 새로 지은 집
4 35.069483 128.979623 5번: 적당한 크기에 조금 오래된 다소 비싼 집
5 35.233308 129.147999 6번: 오래 되었지만 적당한 크기의 싼 집
6 35.214680 129.011909 7번: 넓지만 오래되었고 비싼 집
7 35.121655 129.036808 8번: 오래 되었지만 적절한 가격의 집
8 35.098581 129.015987 9번: 좁지만 최근에 지었고 싼 집
In [87]:
marker_posA.to_excel('data/house_sample.xlsx',index=None, encoding='utf-8') # 파일 저장
In [88]:
marker_posB = pd.read_excel("data/house_sample.xlsx")
marker_posB
Out[88]:
위도 경도 집 정보
0 35.114992 129.082752 1번: 비싸지만 넓고 최근에 지은 집
1 35.228946 129.157009 2번: 적절한 면적과 가격의 집
2 35.196538 129.008752 3번: 좁은데 저렴하지도 않고 오래된 집ㅜ_ㅜ;
3 35.170736 129.115990 4번: 비싸지만 새로 지은 집
4 35.069483 128.979623 5번: 적당한 크기에 조금 오래된 다소 비싼 집
5 35.233308 129.147999 6번: 오래 되었지만 적당한 크기의 싼 집
6 35.214680 129.011909 7번: 넓지만 오래되었고 비싼 집
7 35.121655 129.036808 8번: 오래 되었지만 적절한 가격의 집
8 35.098581 129.015987 9번: 좁지만 최근에 지었고 싼 집
In [89]:
[marker_posB['위도'][0], marker_posB['경도'][0], marker_posB['집 정보'][0]]
Out[89]:
[35.114992, 129.082752, '1번: 비싸지만 넓고 최근에 지은 집']
In [90]:
target_pos = [35.220730, 129.104888] # 금정구 서곡초등학교
baseball_pos = [35.195578, 129.061319] # 동래구 사직 야구장

m = folium.Map(target_pos, min_zoom=11, max_zoom=11)

folium.Circle(location = target_pos, radius = 6000, color='red', fill_color='red').add_to(m)
folium.Circle(location = baseball_pos, radius = 6000, color='yellow', fill_color='black').add_to(m)

for n in range(len(marker_posB)):
    folium.CircleMarker(location = [marker_posB['위도'][n], marker_posB['경도'][n]], 
                        radius = House['거래금액(만원)'][n]/3000, color='blue', fill_color='blue').add_to(m)
    folium.Marker([marker_posB['위도'][n], marker_posB['경도'][n]], popup=marker_posB['집 정보'][n]).add_to(m)
    
folium.Marker(target_pos, popup='서곡초등학교', icon=folium.Icon(color='red')).add_to(m)
folium.Marker(baseball_pos, popup='야구장', icon=folium.Icon(color='black')).add_to(m)

m
Out[90]:
In [91]:
m.save('data/map/map_busan_house_info.html')

구글 API 활용하기

  • 산업수학 아카데미... 마지막 저녁.. 새로 사귄 친구들과 치킨 타임???^^
In [93]:
kb_chicken = pd.read_excel("data/kb_chicken.xlsx")
In [94]:
kb_chicken # 웹 크롤링을 활용하여 자동으로 가져올 수 있음
Out[94]:
상호 주소 가격 평점
0 교땡치킨 경기도 수원시 장안구 영화동 60 15000 3.0
1 땅땡치킨 경기도 수원시 장안구 영화동 영화동 115-5번지 14000 1.0
2 유땡통닭 경기도 수원시 장안구 영화동 161-57 13000 4.0
3 교땡치킨 경기도 수원시 장안구 연무동 249-13 15000 3.8
4 네땡치킨 경기도 수원시 장안구 연무동 연무로 33 15000 3.7
5 삼땡치킨 경기도 수원시 장안구 조원동 519-180 14500 3.9
6 오땡마루 경기도 수원시 장안구 조원1동 조원로 80-1 16000 4.8
In [71]:
import googlemaps

gmap_key = "********************************" # 각자의 Google Maps API 용 Key 입력
gmaps = googlemaps.Client(key=gmap_key)
In [72]:
gmaps.geocode(str(kb_chicken['주소'][0]))[0]
Out[72]:
{'address_components': [{'long_name': '60',
   'short_name': '60',
   'types': ['premise']},
  {'long_name': 'Yeonghwa-dong',
   'short_name': 'Yeonghwa-dong',
   'types': ['political', 'sublocality', 'sublocality_level_2']},
  {'long_name': 'Jangan-gu',
   'short_name': 'Jangan-gu',
   'types': ['political', 'sublocality', 'sublocality_level_1']},
  {'long_name': 'Suwon',
   'short_name': 'Suwon',
   'types': ['locality', 'political']},
  {'long_name': 'Gyeonggi-do',
   'short_name': 'Gyeonggi-do',
   'types': ['administrative_area_level_1', 'political']},
  {'long_name': 'South Korea',
   'short_name': 'KR',
   'types': ['country', 'political']},
  {'long_name': '440-050', 'short_name': '440-050', 'types': ['postal_code']}],
 'formatted_address': '60 Yeonghwa-dong, Jangan-gu, Suwon, Gyeonggi-do, South Korea',
 'geometry': {'location': {'lat': 37.2948004, 'lng': 127.0189059},
  'location_type': 'ROOFTOP',
  'viewport': {'northeast': {'lat': 37.2961493802915,
    'lng': 127.0202548802915},
   'southwest': {'lat': 37.2934514197085, 'lng': 127.0175569197085}}},
 'place_id': 'ChIJt0kgfLhcezUR0eGM_Dy7SFg',
 'plus_code': {'compound_code': '72V9+WH Suwon-si, 경기도 South Korea',
  'global_code': '8Q9972V9+WH'},
 'types': ['street_address']}
In [73]:
gmaps.geocode(str(kb_chicken['주소'][0]))[0]['geometry']
Out[73]:
{'location': {'lat': 37.2948004, 'lng': 127.0189059},
 'location_type': 'ROOFTOP',
 'viewport': {'northeast': {'lat': 37.2961493802915, 'lng': 127.0202548802915},
  'southwest': {'lat': 37.2934514197085, 'lng': 127.0175569197085}}}
In [74]:
gmaps.geocode(str(kb_chicken['주소'][0]))[0]['geometry']['location']
Out[74]:
{'lat': 37.2948004, 'lng': 127.0189059}
In [75]:
lat = []
lng = []

for n in range(len(kb_chicken)):
    lat.append(gmaps.geocode(str(kb_chicken['주소'][n]))[0]['geometry']['location']['lat'])
    lng.append(gmaps.geocode(str(kb_chicken['주소'][n]))[0]['geometry']['location']['lng'])
        
kb_chicken['lat'] = lat
kb_chicken['lng'] = lng
In [76]:
kb_chicken
Out[76]:
상호 주소 가격 평점 lat lng
0 교땡치킨 경기도 수원시 장안구 영화동 60 15000 3.0 37.294800 127.018906
1 땅땡치킨 경기도 수원시 장안구 영화동 영화동 115-5번지 14000 1.0 37.291983 127.020087
2 유땡통닭 경기도 수원시 장안구 영화동 161-57 13000 4.0 37.291860 127.015052
3 교땡치킨 경기도 수원시 장안구 연무동 249-13 15000 3.8 37.293270 127.026374
4 네땡치킨 경기도 수원시 장안구 연무동 연무로 33 15000 3.7 37.294507 127.027500
5 삼땡치킨 경기도 수원시 장안구 조원동 519-180 14500 3.9 37.299098 127.020264
6 오땡마루 경기도 수원시 장안구 조원1동 조원로 80-1 16000 4.8 37.300366 127.016781
In [77]:
target_pos = [37.291934, 127.017168] # KB인재니움; 경기도 수원시 장안구 영화동 171-1

m = folium.Map(target_pos, min_zoom=15, max_zoom=15)

folium.Circle(location = target_pos, radius = 700, color='red', fill_color='red').add_to(m)

for n in range(len(kb_chicken)):
    folium.CircleMarker(location = [kb_chicken['lat'][n], kb_chicken['lng'][n]], 
                        radius = kb_chicken['가격'][n]/500, color='blue', fill_color='blue').add_to(m)
    folium.Marker([kb_chicken['lat'][n], kb_chicken['lng'][n]], 
                   popup=kb_chicken['상호'][n]+', '+str(kb_chicken['가격'][n])+'원, '+'평점: '+str(kb_chicken['평점'][n]), 
                   icon=folium.Icon(color='blue')).add_to(m)
    
folium.Marker(target_pos, popup='KB인재니움', icon=folium.Icon(color='red')).add_to(m)

m
Out[77]:
In [108]:
m.save('data/map/kb_chicken.html')

강연을 마칩니다!!! 수고 많으셨어요~

In [ ]: